﻿using DeHeng_Mes.Model.BossModel;
using DeHeng_Mes.Utils;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
using JsonException = System.Text.Json.JsonException;
using DeHeng_Mes.Service.Plc;
using DeHeng_Mes.Dao;
using DeHeng_Mes.Model.Table;
using S7.Net;
using DeHeng_Mes.Dao.PlcDao;
using DeHeng_Mes.Model.ConfigModel;
using DeHeng_Mes.Constant;
using JsonSerializer = System.Text.Json.JsonSerializer;
using DeHeng_Mes.Model.Boss;
using static DeHeng_Mes.Model.Data.GlueVision;
using System.Linq;
using DeHeng_Mes.Model;
using SqlSugar;
using MappingTable = DeHeng_Mes.Utils.MappingTable;
using DeHeng_Mes.Model.PlcModel;

namespace DeHeng_Mes.Thread
{
    public class FactoryMes
    {


        #region 线程事件变量
        #endregion

        #region 全局成员
        LinePlcToMes plcToMes = new LinePlcToMes();
        List<PlcOrderConfigModel> ReadPlcList = PlcOrderConfigModelList.ReadPlcList;
        Dictionary<string, string> andonDic = AndonConfigModelDic.AndonModel;
        private readonly ErrorStatusDao errorStatusDao = new ErrorStatusDao();
        #endregion


        /// <summary>
        /// 获取工厂Mes下发的订单信息
        /// </summary>
        /// <returns></returns>
        public async Task GetOrderDetails()
        {
            Tools.ProduceLogText("正在开启监听服务...");
            try
            {
                using (HttpListener listener = new HttpListener())
                {
                    // 添加监听地址
                    listener.Prefixes.Add("http://192.168.20.30:7512/");
                    //listener.Prefixes.Add("http://192.168.6.250:8011/");

                    // 启动监听
                    listener.Start();
                    Tools.ProduceLogText("监听服务开启成功!");

                    while (true)
                    {
                        // 异步等待客户端请求
                        HttpListenerContext context = await listener.GetContextAsync();

                        // 接收请求，根据请求URL查找对应的服务方法
                        string requestMethod = MappingTable.UrlAnalysis(context.Request.Url.ToString());

                        // 判断请求对应的方法
                        switch (requestMethod)
                        {
                            case "ProcessRequest":
                                _ = Task.Run(() => ProcessRequest(context));
                                break;
                            case "SpotCheckOk":
                                _ = Task.Run(() => ReportingForWork(context, "点检", 0));
                                break;
                            case "ReceiveReport":
                                _ = Task.Run(() => ReportingForWork(context, "报工", 1));
                                break;
                            case "CheckReport":
                                _ = Task.Run(() => OrderEnd(context));
                                break;
                            case "AdditionalOrder":
                                /*_ = Task.Run(() => AdditionalOrder(context));*/
                                break;
                            case "ISVGlue":
                                _ = Task.Run(() => CollectDataForGluingVisionAsync(context));
                                break;
                            case "GetNgCode":
                                _ = Task.Run(() => FactoryMesGetNgCode(context));
                                break;
                            case "AndonTTS":
                                _ = Task.Run(() => AndonTextToSpeech(context));
                                break;
                            case "AndonDelete":
                                _ = Task.Run(() => AndonDelete(context));
                                break;
                            default:
                                Tools.ProduceLogTextError($"未知的Url，{context.Request.Url}");
                                break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError("监听服务开启失败，原因是：" + ex.Message);
            }
        }

        /// <summary>
        /// 接收工单完成的HTTP请求，解析并将工单状态写入对应PLC。
        /// </summary>
        /// <param name="context">HTTP请求上下文。</param>
        /// <param name="taskName">任务名称，用于响应信息。</param>
        /// <param name="off">点位值，用于设置任务状态。</param>
        private async void ReportingForWork(HttpListenerContext context, string taskName, int off)
        {
            string responseString = string.Empty; // 初始化响应消息
            int statusCode = (int)HttpStatusCode.OK; // 初始化HTTP状态码
            CheckAndWorkReportList checkAndWorkReport = null;
            bool Data = false;

            try
            {
                // 检查HTTP请求方式是否为POST
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求", Data);
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                    await SendResponseAsync(context, responseString, statusCode);
                    return;
                }

                // 读取请求体中的JSON数据
                using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                {
                    string requestBody = await reader.ReadToEndAsync();

                    // 反序列化请求体到对象
                    if (off == 0)
                    {
                        checkAndWorkReport = JsonConvert.DeserializeObject<CheckAndWorkReportList>(requestBody);
                    }
                    else
                    {
                        EndOrder endOrder = JsonConvert.DeserializeObject<EndOrder>(requestBody);
                        checkAndWorkReport = new CheckAndWorkReportList();
                        checkAndWorkReport.LineId = endOrder.LineId;
                        checkAndWorkReport.OrderId = endOrder.OrderId;
                    }

                    // 获取对应的PLC名称
                    string plcName = MappingTable.GetTasksType(checkAndWorkReport.LineId.ToString());

                    // 遍历所有已连接的PLC
                    foreach (var orderModel in PlcOrderConfigModelList.ReadPlcList)
                    {
                        // 如果PLC名称不匹配且无法处理当前工单，则跳过
                        if (!orderModel.PlcName.Equals(plcName)) continue;

                        (bool result, string message) = ProcessOrder1(orderModel, checkAndWorkReport.OrderId, off, taskName, plcName);

                        // 如果匹配或成功处理，则标记为成功并构建响应
                        Data = true;
                        responseString = BuildResponse(result, message, Data);
                        break;
                    }
                }
            }
            catch (JsonException ex)
            {
                // 捕获JSON解析错误，返回400错误
                responseString = BuildResponse(false, "请求数据格式错误", Data);
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError($"解析{taskName}完成数据失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                // 捕获其他服务器内部错误，返回500错误
                responseString = BuildResponse(false, "服务器内部错误", Data);
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError($"下发{taskName}完成错误，原因是：" + ex.Message);
            }
            finally
            {
                // 发送HTTP响应
                await SendResponseAsync(context, responseString, statusCode);
            }
        }

        private (bool result, string message) ProcessOrder1(PlcOrderConfigModel orderModel, string orderId, int off, string taskName, string plcName)
        {
            int count = MappingTable.GetCount(plcName);

            for (int i = 1; i <= count; i++)
            {
                // 从PLC中读取工单数据
                byte[] bytes = orderModel.plc.ReadBytes(DataType.DataBlock, SystemConstant.Order, i == 1 ? 0 : 772 * (i - 1), 256);

                // 解析并比较工单号
                if (orderId.Equals(PlcDao.ParseS7String(bytes)))
                {
                    // 返回写入结果
                    orderModel.plc.WriteBit(DataType.DataBlock, SystemConstant.Order, i == 1 ? 770 : (772 * (i - 1)) + 770, off, true);

                    Tools.ProduceLogText($"{orderId}执行{taskName}成功，已写入PLC状态");
                    int index = 0;
                    while (true)
                    {
                        if (index < 5)
                        {
                            if (string.IsNullOrEmpty(PlcDao.ParseS7String(orderModel.plc.ReadBytes(DataType.DataBlock, SystemConstant.Order, i == 1 ? 0 : 772 * (i - 1), 256))))
                            {
                                return (true, $"{taskName}完成");
                            }
                        }
                        else
                        {
                            return (false, $"{taskName}未完成，PLC未在设定时间内清理工单");
                        }
                        System.Threading.Thread.Sleep(1000);
                        index++;
                    }

                }
            }

            // 未匹配工单号，返回处理失败
            return (true, $"{taskName}失败，在Plc中未找到匹配工单");
        }

        /// <summary>
        /// 处理单个工单，根据PLC中的工单号读取完成状态。
        /// </summary>
        /// <param name="orderModel">PLC模型实例。</param>
        /// <param name="orderId">工单号。</param>
        /// <returns>是否成功处理该工单。</returns>
        private (bool, string) ProcessOrder(PlcOrderConfigModel orderModel, string orderId)
        {

            // 从PLC中读取工单数据
            byte[] bytes = orderModel.plc.ReadBytes(DataType.DataBlock, SystemConstant.DB6008, orderModel.OrderNumInPlc.Equals("1") ? 0 : 772 * (int.Parse(orderModel.OrderNumInPlc) - 1), 256);

            // 解析并比较工单号
            if (orderId.Equals(PlcDao.ParseS7String(bytes)))
            {
                // 返回读取结果
                bool result = (bool)orderModel.plc.Read(DataType.DataBlock, SystemConstant.DB6008, orderModel.OrderNumInPlc.Equals("1") ? 770 : (772 * (int.Parse(orderModel.OrderNumInPlc) - 1)) + 770, VarType.Bit, 4);
                if (result)
                    return (true, "查询成功，允许报工");
                else
                    return (false, "查询成功，未达到下线标准，请检查plc是否存在未完成工序");
            }
            // 未匹配工单号，返回处理失败
            return (false, $"未找到工单{orderId}");
        }

        /// <summary>
        /// 处理单个工单，读取PLC中的工单号并写入完成状态。
        /// </summary>
        /// <param name="orderModel">PLC模型实例。</param>
        /// <param name="orderId">工单号。</param>
        /// <param name="off">点位值。</param>
        /// <returns>是否成功处理该工单。</returns>
        private (bool,string) ProcessOrder(PlcOrderConfigModel orderModel, string orderId, int off, string taskName)
        {
            // 从PLC中读取工单数据
            byte[] bytes = orderModel.plc.ReadBytes(DataType.DataBlock, SystemConstant.DB6008, orderModel.OrderNumInPlc.Equals("1") ? 0 : 772 * (int.Parse(orderModel.OrderNumInPlc) - 1), 256);

            // 解析并比较工单号
            if (orderId.Equals(PlcDao.ParseS7String(bytes)))
            {
                // 返回写入结果
                orderModel.plc.WriteBit(DataType.DataBlock, SystemConstant.DB6008, orderModel.OrderNumInPlc.Equals("1") ? 770 : (772 * (int.Parse(orderModel.OrderNumInPlc) - 1)) + 770, off, true);

                return (true, $"{taskName}完成");
            }

            // 未匹配工单号，返回处理失败
            return (true, $"{taskName}失败，在Plc中未找到匹配工单");
        }


        /// <summary>
        /// 移除安灯任务
        /// </summary>
        /// <param name="context"></param>
        private async void AndonDelete(HttpListenerContext context)
        {
            string responseString = string.Empty;
            int statusCode = (int)HttpStatusCode.OK;

            try
            {
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求");
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                }
                else
                {
                    using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                    {
                        string requestBody = await reader.ReadToEndAsync();

                        // 解析 JSON 数据
                        AndonVoice andonVoice = JsonConvert.DeserializeObject<AndonVoice>(requestBody);

                        // 将解析数据从数据库与缓存删除
                        AndonDao andonDao = new AndonDao();

                        // 检查是否存在相同的安灯编号
                        if (andonDao.QueryById(andonVoice.AndonId) && andonDao.DeleteById(andonVoice.AndonId))
                        {
                            bool isOk = false;
                            lock (andonDic)
                            {
                                isOk = andonDic.Remove(andonVoice.AndonId);
                            }

                            if (isOk)
                            {
                                AndonSpeechSynthesizer.SpeechSynthesizer.SpeakAsyncCancelAll();
                                responseString = BuildResponse(true, "任务完成");
                                Tools.ProduceLogText($"删除了一条安灯报警，安灯编号为：{andonVoice.AndonId}");
                            }
                            else
                                responseString = BuildResponse(false, "任务移除失败");
                        }
                        else
                            responseString = BuildResponse(false, "任务不存在或从线体数据库移除失败");
                    }
                }
            }
            catch (JsonException ex)
            {
                responseString = BuildResponse(false, "请求数据格式错误");
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError("解析安灯数据失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                responseString = BuildResponse(false, "服务器内部错误");
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError("插入安灯数据或缓存错误，原因是：" + ex.Message);
            }
            finally
            {
                await SendResponseAsync(context, responseString, statusCode);
            }
        }

        /// <summary>
        /// 安灯报警信息添加
        /// </summary>
        /// <param name="context"></param>
        private async void AndonTextToSpeech(HttpListenerContext context)
        {
            string responseString = string.Empty;
            int statusCode = (int)HttpStatusCode.OK;

            try
            {
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求");
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                }
                else
                {
                    using (var reader = new StreamReader(context.Request.InputStream, Encoding.UTF8))
                    {
                        string requestBody = await reader.ReadToEndAsync();

                        // 解析 JSON 数据
                        AndonVoice andonVoice = JsonConvert.DeserializeObject<AndonVoice>(requestBody);

                        // 将解析数据存入数据库与缓存
                        AndonDao andonDao = new AndonDao();

                        //检查是否存在相同的安灯编号
                        if (andonDao.QueryById(andonVoice.AndonId))
                            responseString = BuildResponse(false, "请勿重复添加");
                        else
                        {
                            if (andonDao.InsertAndonData(andonVoice))
                                andonDic.Add(andonVoice.AndonId, andonVoice.Voice);
                            responseString = BuildResponse(true, "添加成功");
                            Tools.ProduceLogText($"添加了一条安灯报警，安灯编号为：{andonVoice.AndonId}，安灯报警信息为：{andonVoice.Voice}");
                        }
                    }
                }
            }
            catch (JsonException ex)
            {
                responseString = BuildResponse(false, "请求数据格式错误");
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError("解析安灯数据失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                responseString = BuildResponse(false, "服务器内部错误");
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError("插入安灯数据或缓存错误，原因是：" + ex.Message);
            }
            finally
            {
                await SendResponseAsync(context, responseString, statusCode);
            }
        }

        /// <summary>
        /// 返回本次工单、工序、时间间隔中报错追溯码
        /// </summary>
        /// <param name="context"></param>
        private async void FactoryMesGetNgCode(HttpListenerContext context)
        {
            string responseString = string.Empty;
            int statusCode = (int)HttpStatusCode.OK;

            try
            {
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求");
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                }
                else
                {
                    using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                    {
                        string requestBody = await reader.ReadToEndAsync();

                        // 解析 JSON 数据
                        BossGetNgCode jsonData = JsonConvert.DeserializeObject<BossGetNgCode>(requestBody);

                        // 根据条件查询数据
                        CodeTraceDao codeTraceDao = new CodeTraceDao();

                        List<PadTraceCode> padTraceCodes = codeTraceDao.GetCodes(jsonData.Operation, jsonData.OrderId, jsonData.Time);

                        if (padTraceCodes != null && padTraceCodes.Count > 0)
                        {
                            responseString = BuildResponse(true, "查询成功", padTraceCodes);
                            Tools.ProduceLogText($"{jsonData.OrderId}订单，{jsonData.Operation}工序，{jsonData.Time}Ng件数据查询成功！");
                        }
                        else
                        {
                            responseString = BuildResponse(true, "未查询到相关的数据", null);
                            Tools.ProduceLogText($"{jsonData.OrderId}订单，{jsonData.Operation}工序，{jsonData.Time}Ng件数据查询成功！但是未查询到数据...");
                        }
                    }
                }
            }
            catch (JsonException ex)
            {
                responseString = BuildResponse(false, "请求数据格式错误");
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError("查询Ng二维码失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                responseString = BuildResponse(false, "服务器内部错误");
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError("查询Ng二维码失败，原因是：" + ex.Message);
            }
            finally
            {
                await SendResponseAsync(context, responseString, statusCode);
            }
        }


        /// <summary>
        /// 追加订单服务
        /// </summary>
        /// <param name="context"></param>
        public async Task AdditionalOrder(HttpListenerContext context)
        {
            string responseString = string.Empty;
            int statusCode = (int)HttpStatusCode.OK;

            try
            {
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求");
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                }
                else
                {
                    using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                    {
                        string requestBody = await reader.ReadToEndAsync();

                        // 解析 JSON 数据
                        OrderPlan jsonData = JsonConvert.DeserializeObject<OrderPlan>(requestBody);

                        // 检查缓存中是否已有该工单
                        bool orderFound = false;
                        if (ReadPlcList != null && ReadPlcList.Count > 0)
                        {
                            foreach (var item in ReadPlcList)
                            {
                                if (item.orderPlan.OrderId.Equals(jsonData.OrderId))
                                {
                                    orderFound = true;

                                    // 读取PLC中的计划数量
                                    int plcCount = (int)item.plc.Read(DataType.DataBlock, 6008, 514 * int.Parse(item.OrderNumInPlc), VarType.Int, 4);

                                    // 计算新数量并写入PLC
                                    int produceNum = int.Parse(jsonData.ProduceNum.ToString()) + plcCount;
                                    item.plc.Write(DataType.DataBlock, 6008, 514 * int.Parse(item.OrderNumInPlc), produceNum);

                                    // 更新数据库中计划数量
                                    OrderDao orderDao = new OrderDao();
                                    orderDao.AdditionalOrder(jsonData.OrderId, produceNum);

                                    responseString = BuildResponse(true, "追加完成");
                                    break;
                                }
                            }
                        }

                        if (!orderFound)
                        {
                            responseString = BuildResponse(false, "不存在的工单");
                        }
                    }
                }
            }
            catch (JsonException ex)
            {
                responseString = BuildResponse(false, "请求数据格式错误");
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError("工厂Mes工单追加失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                responseString = BuildResponse(false, "服务器内部错误");
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError("工厂Mes工单追加失败，服务器内部错误：" + ex.Message);
            }
            finally
            {
                await SendResponseAsync(context, responseString, statusCode);
            }
        }


        /// <summary>
        /// 检测是否可以报工
        /// </summary>
        /// <param name="context"></param>
        public async Task OrderEnd(HttpListenerContext context)
        {
            string responseString = string.Empty; // 初始化响应消息
            int statusCode = (int)HttpStatusCode.OK; // 初始化HTTP状态码
            bool Data = false;
            try
            {
                // 检查HTTP请求方式是否为POST
                if (context.Request.HttpMethod != "POST")
                {
                    responseString = BuildResponse(false, "未知请求", Data);
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                    await SendResponseAsync(context, responseString, statusCode);
                    return;
                }

                // 读取请求体中的JSON数据
                using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                {
                    string requestBody = await reader.ReadToEndAsync();

                    // 反序列化请求体到对象
                    CheckAndWorkReportList checkAndWorkReport = JsonConvert.DeserializeObject<CheckAndWorkReportList>(requestBody);

                    // 获取对应的PLC名称
                    string plcName = MappingTable.GetTasksType(checkAndWorkReport.LineId.ToString());
                    // 遍历所有已连接的PLC
                    foreach (var orderModel in PlcOrderConfigModelList.ReadPlcList)
                    {
                        // 如果PLC名称不匹配且无法处理当前工单，则跳过
                        if (!orderModel.PlcName.Equals(plcName)) continue;

                        (bool result, string message) = ProcessOrder(orderModel, checkAndWorkReport.OrderId, plcName);

                        // 如果匹配或成功处理，则标记为成功并构建响应
                        Data = true;
                        responseString = BuildResponse(result, message, Data);
                        return;
                    }
                }
            }
            catch (JsonException ex)
            {
                // 捕获JSON解析错误，返回400错误
                responseString = BuildResponse(false, "请求数据格式错误", Data);
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError($"报工查询接口解析数据失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                // 捕获其他服务器内部错误，返回500错误
                responseString = BuildResponse(false, "服务器内部错误", Data);
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError($"报工查询接口解析数据错误，原因是：" + ex.Message);
            }
            finally
            {
                // 发送HTTP响应
                await SendResponseAsync(context, responseString, statusCode);
            }
        }

        /// <summary>
        /// 处理单个工单，根据PLC中的工单号读取完成状态。
        /// </summary>
        /// <param name="orderModel">PLC模型实例。</param>
        /// <param name="orderId">工单号。</param>
        /// <returns>是否成功处理该工单。</returns>
        private (bool, string) ProcessOrder(PlcOrderConfigModel orderModel, string orderId, string plcName)
        {
            int count = MappingTable.GetCount(plcName);

            for (int i = 1; i <= count; i++)
            {
                // 从PLC中读取工单数据
                byte[] bytes = orderModel.plc.ReadBytes(DataType.DataBlock, 6008, i == 1 ? 0 : 772 * (i - 1), 256);

                string v = PlcDao.ParseS7String(bytes);

                // 解析并比较工单号
                if (orderId.Equals(PlcDao.ParseS7String(bytes)))
                {
                    // 计算字节地址（假设每个结构体间隔772字节）
                    int byteAddress = i == 1 ? 770 : 772 * (i - 1) + 770;

                    // 读取整个字节（VarType.Byte 表示读取一个字节）
                    byte data = (byte)orderModel.plc.Read(
                        DataType.DataBlock,
                        6008,
                        byteAddress,
                        VarType.Byte,  // 读取类型为字节
                        1             // 读取1个字节
                    );

                    bool result = (data & (1 << 4)) != 0;

                    if (result)
                        return (true, "查询成功，允许报工");
                    else
                        return (false, "查询成功，未达到下线标准，请检查plc是否存在未完成工序");
                }
            }


            // 未匹配工单号，返回处理失败
            return (false, $"未找到工单{orderId}");
        }

        /// <summary>
        /// 处理接收订单的 HTTP 请求服务
        /// </summary>
        /// <param name="context">HTTP 请求上下文，包含请求与响应信息</param>
        public async Task ProcessRequest(HttpListenerContext context)
        {
            // 初始化响应内容和状态码
            string responseString = string.Empty; // 存储最终的响应内容
            int statusCode = (int)HttpStatusCode.OK; // 默认状态码为200 (OK)

            try
            {
                // 确保请求是 POST 方法
                if (context.Request.HttpMethod != "POST")
                {
                    // 如果请求不是POST方法，则返回未知请求的响应信息
                    responseString = BuildResponse(false, "未知请求");
                    Tools.ProduceLogText($"接收到一个未知的请求方式，请求方式为：{context.Request.HttpMethod}");
                }
                else
                {
                    // 使用 StreamReader 读取请求数据流中的内容
                    using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                    {
                        // 异步读取请求体内容并转换为字符串
                        string requestBody = await reader.ReadToEndAsync();

                        // 将请求体的 JSON 数据反序列化为 OrderPlan 对象
                        OrderPlan jsonData = JsonConvert.DeserializeObject<OrderPlan>(requestBody);

                        // 检查订单是否已存在于数据库或缓存中
                        if (OrderAlreadyExists(jsonData.OrderId))
                        {
                            //判断状态是否创建
                            bool status = GetOrderStatus(jsonData.OrderId);

                            if (!status)
                            {
                                //接收工单并且下发Plc
                                responseString = ReceiveAndSendOrder(jsonData);
                            }
                            else
                            {
                                // 如果订单已存在，生成重复订单的响应内容
                                responseString = BuildResponse(false, "该工单号已存在生产队列中，请勿重复下单");
                                Tools.ProduceLogTextError($"数据库或生产缓存中已存在{jsonData.OrderId},请勿重复下单避免影响正常工单接收！");
                            }
                        }
                        else
                        {
                            bool isOk = InsertOrder(jsonData.LineId, jsonData.MaterialCode, jsonData.PartId, jsonData.PartName, jsonData.OrderId, jsonData.ProduceNum, DateTime.Now, jsonData.ProcessCodes);

                            if (isOk)
                            {
                                // 如果订单不存在，则接收订单并下发至PLC
                                responseString = ReceiveAndSendOrder(jsonData);

                                SubMessage subMessage = JsonConvert.DeserializeObject<SubMessage>(responseString);

                                if (!subMessage.Success)
                                {
                                    // 回滚
                                    DeleteOrder(jsonData.OrderId);
                                }
                            }
                        }
                    }
                }
            }
            catch (JsonException ex)
            {
                // 捕获 JSON 格式解析异常，表示请求数据格式错误，设置状态码为400 (Bad Request)
                responseString = BuildResponse(false, "请求数据格式错误");
                statusCode = (int)HttpStatusCode.BadRequest;
                Tools.ProduceLogTextError("工厂Mes工单接收失败，原因是：" + ex.Message);
            }
            catch (Exception ex)
            {
                // 捕获所有其他异常，表示服务器内部错误，设置状态码为500 (Internal Server Error)
                responseString = BuildResponse(false, "服务器内部错误");
                statusCode = (int)HttpStatusCode.InternalServerError;
                Tools.ProduceLogTextError("工厂Mes工单接收失败，服务器内部错误：" + ex.Message);
            }
            finally
            {
                // 发送响应数据
                await SendResponseAsync(context, responseString, statusCode);
            }
        }

        /// <summary>
        /// 删除工单数据
        /// </summary>
        /// <param name="orderId"></param>
        private void DeleteOrder(string orderId)
        {
            OrderDao orderDao = new OrderDao();

            orderDao.DeleteOrder(orderId);
        }

        /// <summary>
        /// 初始化工单数据
        /// </summary>
        /// <param name="lineId"></param>
        /// <param name="orderId"></param>
        /// <param name="produceNum"></param>
        /// <param name="now"></param>
        /// <param name="processCodes"></param>
        private bool InsertOrder(string lineId, string MaterialCode, string partId, string partName, string orderId, decimal produceNum, DateTime now, List<string> processCodes)
        {
            OrderStatus orderStatus = new OrderStatus();

            OrderDao orderDao = new OrderDao();

            orderStatus.LineName = lineId.ToString();
            orderStatus.OrderId = orderId;
            orderStatus.MaterialCode = MaterialCode;
            orderStatus.PartId = partId;
            orderStatus.PartName = partName;
            orderStatus.ProductionPlan = produceNum.ToString();
            orderStatus.OrderIssuedTime = now;
            orderStatus.Status = "0";
            orderStatus.StartWorkStatus = SystemConstant.illegal;
            orderStatus.ProcessCode = string.Join(",", processCodes);

            int count = orderDao.InsertOrder(orderStatus);

            return (count > 0) ? true : false;
        }


        /// <summary>
        /// 获取订单状态
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        private bool GetOrderStatus(string orderId)
        {
            OrderDao orderDao = new OrderDao();
            return orderDao.GetOrderStatus(orderId);
        }


        /// <summary>
        /// 检查订单是否存在缓存或者数据库中
        /// </summary>
        /// <param name="orderId"></param>
        /// <returns></returns>
        private bool OrderAlreadyExists(string orderId)
        {
            OrderDao orderDao = new OrderDao();
            if (orderDao.OrderIsSave(orderId)) return true;

            foreach (var plcList in ReadPlcList)
            {
                if (plcList.orderPlan.OrderId.Equals(orderId))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 接收工单并且下发Plc
        /// </summary>
        /// <param name="jsonData"></param>
        /// <param name="context"></param>
        /// <returns></returns>
        private string ReceiveAndSendOrder(OrderPlan jsonData)
        {
            // 获取PlcName
            string plcName = MappingTable.GetTasksType(jsonData.LineId);

            // 根据请求进一步获取需要启动的Plc名称下发
            Tools.ProduceLogText($"接收到一个工单， 工单号：{jsonData.OrderId}，线体编号为：{jsonData.LineId}，物料编码：{jsonData.MaterialCode}，物料名称为：{jsonData.PartName}，数量：{jsonData.ProduceNum}，下挂工序号为：{string.Join(",", jsonData.ProcessCodes)}");

            // 创建订单配置模型并启动数据读取线程
            PlcOrderConfigModel orderConfigModel = CreatePlcConfigModel(jsonData, jsonData.MaterialCode, plcName);
            if (orderConfigModel != null)
            {
                //缓存中添加订单模型
                ReadPlcList.Add(orderConfigModel);

                return BuildResponse(true, "工单接收并下发Plc成功");
            }
            return BuildResponse(false, "请检查Plc连接状态或是否重复下单");
        }

        /// <summary>
        /// 构建响应
        /// </summary>
        /// <param name="success"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        private string BuildResponse(bool success, string message) =>
            JsonConvert.SerializeObject(new { Success = success, Message = message });

        private string BuildResponseISV(string success, string message) => "[{\"message\" : \"读取成功\", \"success\":\"true\"}]";

        private string BuildResponse(bool success, string message, object data) =>
            JsonConvert.SerializeObject(new { Success = success, Message = message, Data = data });

        /// <summary>
        /// 发送响应
        /// </summary>
        /// <param name="context"></param>
        /// <param name="responseString"></param>
        /// <param name="statusCode"></param>
        /// <returns></returns>
        private async Task SendResponseAsync(HttpListenerContext context, string responseString, int statusCode)
        {
            // 将响应字符串转换为 UTF-8 字节数组，以便写入到响应流中
            byte[] buffer = Encoding.UTF8.GetBytes(responseString);

            // 设置响应内容的长度（字节数），ContentLength64 告诉客户端响应体的大小，便于接收完整的响应数据
            context.Response.ContentLength64 = buffer.Length;

            // 设置响应的内容类型为 JSON，告知客户端响应的数据格式
            context.Response.ContentType = "application/json";

            // 设置响应的 HTTP 状态码，指示请求的处理结果状态
            context.Response.StatusCode = statusCode;

            // 异步写入响应内容到输出流，将字节数组内容从起始位置写到响应流中
            await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);

            // 关闭响应输出流，表示响应已经完成，释放资源
            context.Response.OutputStream.Close();
        }


        /// <summary>
        /// 创建并初始化 PLC 订单配置模型
        /// </summary>
        /// <param name="jsonData">包含订单信息的 OrderPlan 对象</param>
        /// <param name="requestUrl">当前请求的 URL 地址</param>
        /// <returns>返回初始化后的 PlcConfigModel 对象，或在失败时返回 null</returns>
        public PlcOrderConfigModel CreatePlcConfigModel(OrderPlan jsonData, string MaterialCode, string plcName)
        {

            // 实例化并初始化 LineMesToPlc，用于生成 PLC 订单配置模型
            var lineToPlc = new LineMesToPlc();
            (Plc plc, string orderNum) = lineToPlc.OrderToPlc(jsonData, MaterialCode, plcName);

            //初始化订单模型
            PlcOrderConfigModel orderConfigModel = null;

            if (!string.IsNullOrEmpty(orderNum))
            {
                // 若写入成功，则初始化订单模型，填入数据并返回
                if (plc != null)
                {
                    orderConfigModel = new PlcOrderConfigModel()
                    {
                        PlcName = plcName,
                        plc = plc,
                        OrderNumInPlc = orderNum,
                        GetCodeStatus = false,
                        GetVisionCodeStatus = false,
                        orderPlan = new OrderPlan()
                        {
                            OrderId = jsonData.OrderId,
                            LineId = jsonData.LineId,
                            PartId = jsonData.PartId,
                            MaterialCode = jsonData.MaterialCode,
                            ProduceNum = jsonData.ProduceNum,
                            ProcessCodes = jsonData.ProcessCodes,
                            StartTime = "",
                        }
                    };
                }
            }

            return orderConfigModel;
        }


        /// <summary>
        /// 开局防错判断
        /// </summary>
        public async void OrderIsOk()
        {
            // 日志输出标识
            bool isOut = true;

            await Task.Delay(5000);


            // 初始化Plc连接缓存
            List<string> plcConfigModels = PlcConnectionManager.plcContainer
                .Where(item => !item.isConnected)
                .Select(item => item.name)
                .ToList();

            // 延迟5秒，先启动Plc连接
            await Task.Delay(5000);

            // 检查连接状态并查询工单
            foreach (var item in PlcConnectionManager.plcContainer)
            {
                if (item.isConnected)
                    QueryOrderInPlc(item);
            }

            // 循环检查未连接的PLC
            while (plcConfigModels.Any())
            {
                // 再次检查未连接的PLC
                for (int i = plcConfigModels.Count - 1; i >= 0; i--)
                {
                    var itemName = plcConfigModels[i];
                    var plc = PlcConnectionManager.plcContainer.FirstOrDefault(p => p.name == itemName);

                    if (plc == null || !plc.isConnected)
                    {
                        if (plc != null && isOut)
                            Tools.ProduceLogTextError($"{plc.nick}未连接，无法检测是否存在生产中工单");  // 记录日志但不重复添加到缓存
                    }
                    else
                    {
                        // 查询是否存在订单数据，如果有订单数据那么重新配置订单模型，加入缓存
                        QueryOrderInPlc(plc);
                        plcConfigModels.RemoveAt(i);
                    }
                }
                isOut = false;

                await Task.Delay(1000);
            }
        }

        /// <summary>
        /// 重新配置工单模型
        /// </summary>
        /// <param name="plcConfigModel"></param>
        private void QueryOrderInPlc(PlcConfigModel plcConfigModel)
        {

            // 初始化订单查询类和字典
            OrderDao orderDao = new OrderDao();
            Dictionary<OrderPlan, Dictionary<string, string>> orderDic = new Dictionary<OrderPlan, Dictionary<string, string>>();

            Tools.ProduceLogText($"正在重新启动Plc:{plcConfigModel.nick}的工单读取线程");
            try
            {
                int repeatTimes = MappingTable.GetCount(plcConfigModel.name);

                for (int i = 1; i <= repeatTimes; i++)
                {
                    byte[] orderIdBytes = plcConfigModel.plc.ReadBytes(DataType.DataBlock, SystemConstant.DB6008, i == 1 ? 0 : 772 * (i - 1), 256);
                    string orderId = PlcDao.ParseS7String(orderIdBytes);

                    if (!string.IsNullOrEmpty(orderId))
                    {
                        OrderStatus orderStatus = orderDao.GetOrder(orderId);
                        if (orderStatus != null)
                        {

                            OrderPlan orderPlan = new OrderPlan()
                            {
                                OrderId = orderStatus.OrderId,
                                MaterialCode = orderStatus.MaterialCode,
                                PartId = orderStatus.PartId,
                                ProduceNum = Convert.ToInt32(decimal.Parse(orderStatus.ProductionPlan)),
                                ProcessCodes = orderStatus.ProcessCode.Split(',').ToList(),
                                StartTime = (string.IsNullOrEmpty(orderStatus.StartTime.ToString()) || DateTime.MinValue == orderStatus.StartTime) ? "" : orderStatus.StartTime.ToString(),
                            };

                            orderDic[orderPlan] = new Dictionary<string, string> { { orderStatus.Status == null ? "" : orderStatus.Status, i.ToString() } };
                        }
                        else
                        {
                            Tools.ProduceLogTextError($"{plcConfigModel.nick}:{i}号工单缓存中找到工单:{orderId}，但是数据库中不存在该缓存数据，配置失败");
                            continue;
                        }
                    }
                    else
                    {
                        Tools.ProduceLogText($"{plcConfigModel.nick}:{i}号工单缓存中不存在缓存工单");
                    }
                }

                foreach (var order in orderDic)
                {
                    foreach (var statusOff in order.Value)
                    {
                        PlcOrderConfigModel orderConfigModel = new PlcOrderConfigModel
                        {
                            PlcName = plcConfigModel.name,
                            plc = plcConfigModel.plc,
                            OrderNumInPlc = statusOff.Value,
                            GetCodeStatus = false,
                            GetVisionCodeStatus = false,
                            orderPlan = order.Key,
                        };

                        if (!statusOff.Key.Equals("2"))
                        {
                            ReadPlcList.Add(orderConfigModel);
                            Tools.ProduceLogText($"{plcConfigModel.nick}成功重新配置一个工单模型，工单号为{order.Key.OrderId}，线程池中已包含{ReadPlcList.Count}个工单");
                        }
                        else
                        {
                            Tools.ProduceLogTextError($"检测到{plcConfigModel.nick}工单接收缓存存在已完成工单，请检查Plc程序，工单号为{order.Key.OrderId}，线程池中已包含{ReadPlcList.Count}个工单");
                        }
                    }
                }
                Tools.ProduceLogText($"{plcConfigModel.nick}重读线程结束！");
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError($"{plcConfigModel.nick}重新启动工单读取线程失败，原因是：" + ex.Message);
            }
        }


        /// <summary>
        /// 涂胶视觉
        /// </summary>
        private async Task CollectDataForGluingVisionAsync(HttpListenerContext context)
        {
            string sharePath = string.Empty;
            string shareImgPath = string.Empty;
            string savePath = string.Empty;
            string userName = string.Empty;
            string saveImgPath = string.Empty;
            string password = string.Empty;
            string code = string.Empty;
            ProcessDao processDao = new ProcessDao();
            List<string> savedFiles = new List<string>();
            List<TraceGlueVision> traceGlueVisionLists = new List<TraceGlueVision>();
            try
            {
                using (var reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding))
                {
                    string jsonContent = reader.ReadToEnd();
                    string cleanedString = jsonContent.StartsWith("json=")
                                         ? jsonContent.Substring("json=".Length)
                                         : jsonContent;
                    List<TraceGlueVision> records = new List<TraceGlueVision>();
                    Rootobject jsonData = JsonSerializer.Deserialize<Rootobject>(cleanedString);
                    // 将包含 Error 的所有数组属性存入列表
                    // 创建包含Error属性的字典，将属性名称与对应数组关联
                    var errorDictionary = new Dictionary<string, string[]>
                    {
                        { "AreaError", jsonData.AreaError },
                        { "GapError", jsonData.GapError },
                        { "PositionError", jsonData.PositionError },
                        { "ThickError", jsonData.ThickError },
                        { "ThinError", jsonData.ThinError }
                    };
                    if (jsonData.GlueWidth != null)
                    {
                        foreach (var glueWidth in jsonData.GlueWidth)
                        {
                            var glueVision = new TraceGlueVision();
                            glueVision.TraceId = jsonData.VinCode;
                            glueVision.GlueId = glueWidth.frame;
                            glueVision.RobotId = jsonData.RobotNo.ToString();
                            glueVision.CoatingWidth = glueWidth.beadWidth.ToString();
                            string frameValue = glueWidth.frame;
                            // 使用 LINQ 查询查找包含匹配项的 Error 属性
                            var matchingErrorProperty = errorDictionary
                                .Where(entry => entry.Value != null && entry.Value.Contains(frameValue))
                                .Select(entry => entry.Key) // 获取匹配的属性名称
                                .FirstOrDefault(); // 获取第一个匹配项（如果有）
                            if (matchingErrorProperty != null)
                            {
                                glueVision.ProcessResult = matchingErrorProperty;
                            }
                            else
                            {
                                glueVision.ProcessResult = "OK";
                            }
                            records.Add(glueVision);
                            code = glueVision.TraceId;
                        }
                    }
                    if (records.Count > 0)
                    {
                        processDao.InsertGlueVisionData(records);
                    }
                    string responseString = BuildResponseISV("true", "数据接收成功");
                    int statusCode = (int)HttpStatusCode.OK;
                    await SendResponseAsync(context, responseString, statusCode);
                    Tools.ProduceLogText($"ISV数据采集成功，采集到{records.Count}条数据，追溯码为{jsonData.VinCode}");
                }
            }
            catch (Exception ex)
            {
                Tools.ProduceLogTextError($"ISV数据采集失败，原因是：{ex.Message}");
            }
        }

        /// <summary>
        /// 辅助方法用于获取字符串属性值，如果属性不存在或值为 null，则返回空字符串
        /// </summary>
        /// <param name="element"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        private static string GetStringOrDefault(JsonElement element, string propertyName)
        {
            return element.TryGetProperty(propertyName, out JsonElement prop) && prop.ValueKind != JsonValueKind.Null
                ? prop.GetString()
                : "";
        }
    }
}